#include "stdafx.h"
#include "ZServerSocketNetworkController.h"
#include "ZAcceptor.h"
#include "ZAsyncSocket.h"
#include "ZStream.h"
#include "ZUtility.h"
#include <sstream>

#pragma	warning(disable:4355)

namespace	Z	{

//------------------------------------------------------------------------------------------------------------------------
ServerSocketNetworkController::ServerSocketNetworkController(u_short port, size_t numConcurrentThreads)
:	SocketNetworkController(numConcurrentThreads),
	mAcceptor(new Acceptor(this, port))
{
}

ServerSocketNetworkController::~ServerSocketNetworkController()
{
}

bool ServerSocketNetworkController::start(MessageReceiver* pMessageReceiver)
{
	if(!SocketNetworkController::start(pMessageReceiver))	{
		return false;
	}

	return mAcceptor->start();
}

void ServerSocketNetworkController::cleanup()
{
	mAcceptor->destroy();

	SocketNetworkController::cleanup();

	destroySockets();
}

void ServerSocketNetworkController::destroySockets()
{
	rwmutex_t::scoped_lock lock(mSocketLock, true);

	for(Sockets::iterator i = mSockets.begin(); i != mSockets.end(); ++i){
		delete i->second;
	}
	mSockets.clear();
}

bool ServerSocketNetworkController::onCreate(AsyncSocket* pSocket)
{
	if(!SocketNetworkController::onCreate(pSocket))	{
		return false;
	}

	if(!pSocket->setKeepAlive(10000, 1000))	{
		return false;
	}
	
	rwmutex_t::scoped_lock lock(mSocketLock, true);

	const bool result	= mSockets.insert(Sockets::value_type(pSocket->getNetworkId(), pSocket)).second;
	assert(result);
	if(!result)
		return false;
	pSocket->reference();
	return pSocket->receive();
}

bool ServerSocketNetworkController::onClose(NetworkId kNetworkId, bool graceful, bool notify)
{
	rwmutex_t::scoped_lock lock(mSocketLock, true);

	if(!SocketNetworkController::onClose(kNetworkId, graceful, notify))
		return false;

	AsyncSocket* pSocket	= getSocket(kNetworkId);
	assert(pSocket != nullptr);
	deletePtr(pSocket);
	mSockets.erase(kNetworkId);
	return true;
}

bool ServerSocketNetworkController::onIoComplete(NetworkId kNetworkId, size_t bytesTransferred, OVERLAPPED* pOverlapped)
{
	rwmutex_t::scoped_lock	lock(mSocketLock, false);

	return SocketNetworkController::onIoComplete(kNetworkId, bytesTransferred, pOverlapped);
}

AsyncSocket* ServerSocketNetworkController::getSocket(NetworkId kNetworkId)	const
{
	Sockets::const_iterator i = mSockets.find(kNetworkId);
	if(i == mSockets.end())
		return nullptr;
	return i->second;
}

void ServerSocketNetworkController::send(Stream* pStream, NetworkId kNetworkId)
{
	rwmutex_t::scoped_lock	lock(mSocketLock, false);

	if(kNetworkId == ServerSocketNetworkController::all)	{
		for(Sockets::iterator i = mSockets.begin(); i != mSockets.end(); ++i)	{
			i->second->send(new Stream(*pStream));
		}
		deletePtr(pStream);
	}
	else	{
		SocketNetworkController::send(pStream, kNetworkId);
	}
}

void ServerSocketNetworkController::shutdown(NetworkId kNetworkId)
{
	rwmutex_t::scoped_lock	lock(mSocketLock, false);

	AsyncSocket* pSocket	= getSocket(kNetworkId);
	if(pSocket == nullptr)
		return;

	pSocket->shutdown();
	postCompletionStatus(SocketNetworkController::close, 0, reinterpret_cast<OVERLAPPED*>(kNetworkId));
}

std::string ServerSocketNetworkController::getAddress(NetworkId kNetworkId)	const
{
	std::ostringstream ostr;

	rwmutex_t::scoped_lock	lock(mSocketLock, false);
	AsyncSocket* pSocket	= getSocket(kNetworkId);
	if(pSocket == nullptr)
		return ostr.str();

	SOCKADDR_IN sin;
	zeroise(sin);
	int namelen	= sizeof(sin);
	if(::getpeername(pSocket->getHandle(), (SOCKADDR*)&sin, &namelen) == SOCKET_ERROR)
		return ostr.str();

	ostr << (int)sin.sin_addr.s_net << '.'
		<< (int)sin.sin_addr.s_host << '.'
		<< (int)sin.sin_addr.s_lh << '.'
		<< (int)sin.sin_addr.s_impno;
	return ostr.str();
}

}